/// \file
/// \ingroup tutorial_http
///  This program demonstrates access control to the THttpServer with digest methods.
///  Authentication file auth.txt was generated with following shell commands:
/// ~~~
///    [shell]  htdigest -c auth.txt root guest
///          typing <empty> password for guest account
///    [shell]  htdigest auth.txt root admin
///          typing 'admin' as password for admin account
/// ~~~
///  When macro started and opening in browser with url
/// ~~~
///      http://localhost:8080
/// ~~~
///  User name and password will be requested. One should
///  either specify guest account without password or
///  admin account with password 'admin'
///
///  User with guest account only can monitor histograms
///  User with admin account see commands, which can be executed
///
/// \macro_code
///
/// \author Sergey Linev

#include "TH1.h"
#include "TH2.h"
#include "TRandom3.h"
#include "TSystem.h"
#include "THttpServer.h"

void httpaccess()
{
   // create histograms
   TH1D *hpx = new TH1D("hpx","This is the px distribution",100,-4,4);
   hpx->SetFillColor(48);
   hpx->SetDirectory(0);
   TH2D *hpxpy = new TH2D("hpxpy","py vs px",40,-4,4,40,-4,4);
   hpxpy->SetDirectory(0);

   if (gSystem->AccessPathName("auth.txt")!=0) {
      printf("Please start macro from directory where auth.txt file is available\n");
      printf("It required to supply authentication information for the http server\n");
      return;
   }

   // start http server
   THttpServer* serv = new THttpServer("http:8080?auth_file=auth.txt&auth_domain=root");

   // or start FastCGI server, where host server (like Apache or lighttpd) should enable own authentication
   // for apache one should add correspondent module and authentication for fastcgi location
   // for lighttpd one add following lines to configuration file:
   //   server.modules += ( "mod_auth" )
   //   auth.backend = "htdigest"
   //   auth.backend.htdigest.userfile = "/srv/auth/auth.txt"
   //   auth.require = ( "/root.app" => ( "method" => "digest", "realm" => "root", "require" => "valid-user" ))
   // THttpServer* serv = new THttpServer("fastcgi:9000");

   // One could specify location of newer version of JSROOT
   // serv->SetJSROOT("https://root.cern.ch/js/latest/");
   // serv->SetJSROOT("http://jsroot.gsi.de/latest/");

   // register histograms
   serv->Register("/", hpx);
   serv->Register("/", hpxpy);

   // register commands, invoking object methods
   serv->RegisterCommand("/ResetHPX","/hpx/->Reset();", "button;rootsys/icons/ed_delete.png");
   serv->SetItemField("/ResetHPX","_update_item", "hpx"); // let browser update histogram view after commands execution
   serv->RegisterCommand("/ResetHPXPY","/hpxpy/->Reset();", "button;rootsys/icons/bld_delete.png");
   serv->SetItemField("/ResetHPXPY","_update_item", "hpxpy"); // let browser update histogram view after commands execution
   // here also example how command with arguments can be invoked
   serv->RegisterCommand("/RebinHPX","/hpx/->Rebin(%arg1%);", "button;rootsys/icons/ed_execute.png");
   serv->SetItemField("/RebinHPX","_update_item", "hpx"); // let browser update histogram view after commands execution

   // these two commands fully hidden for other accounts,
   // only admin can see and execute these commands
   serv->Restrict("/ResetHPX",  "visible=admin");
   serv->Restrict("/ResetHPXPY", "visible=admin");

   // this command visible for other, but will be refused (return false)
   // when executed from any other account
   serv->Restrict("/RebinHPX", "allow=admin");

   // Fill histograms randomly
   TRandom3 random;
   Float_t px, py;
   const Long_t kUPDATE = 1000;
   Long_t cnt = 0;
   while (kTRUE) {
      random.Rannor(px,py);
      hpx->Fill(px);
      hpxpy->Fill(px,py);

      // IMPORTANT: one should regularly call ProcessEvents
      if (cnt++ % kUPDATE == 0) {
         if (gSystem->ProcessEvents()) break;
      }
   }
}
